﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using VemTransporte.Models.Basica;
using VemTransporte.Models.Fachada;
using System.IO;
using System.Runtime.Serialization.Json;
using VemTransporte.Models.Factory;
using System.Web;
using System.IO.Compression;
using System.Drawing;
using System.Net;
using System.Xml.Linq;

namespace VemTransporte
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "ServiceWebUsuario" in code, svc and config file together.
    [ServiceContract]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    public class ServiceWebUsuario
    {
        [WebGet(UriTemplate = "DataHoraServidor")]
        public DateTime Date()
        {
            return System.DateTime.Now;
        }

        [WebGet(UriTemplate = "Logar?email={email}&senha={senha}")]
        [OperationContract]
        public string UsuarioLogar(string email, string senha)
        {
            string retorno = "[{'ERROR':'Usuário não encontrado!'}]";

            try
            {

                Usuario usuarioLogado = Fachada.Instance.ProcurarUsuarioPorEmailESenha(email.Trim(), senha.Trim());

                if (usuarioLogado != null)
                {

                    List<Object> lista = new List<Object>();

                    Endereco end = usuarioLogado.Endereco;

                    lista.Add(usuarioLogado);
                    foreach (UsuarioLinha linhas in usuarioLogado.UsuarioLinhas)
                    {
                        lista.Add(linhas.Linha);
                    }

                    using (MemoryStream ms = new MemoryStream())
                    {
                        DataContractJsonSerializer ser = new DataContractJsonSerializer(lista.GetType());
                        ser.WriteObject(ms, lista);
                        retorno = System.Text.Encoding.UTF8.GetString(ms.ToArray());
                    }/**/




                    /*using (MemoryStream ms = new MemoryStream())
                    {
                        DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Usuario));
                        ser.WriteObject(ms, usuarioLogado);
                        retorno = System.Text.Encoding.UTF8.GetString(ms.ToArray());
                    }/**/
                }
            }
            catch (Exception e)
            {
                retorno = "[{'ERROR':'" + e.Message + "'}]";
            }

            return retorno;
        }

        [OperationContract]
        [WebInvoke(
            Method = "POST",
            BodyStyle = WebMessageBodyStyle.WrappedRequest,
            ResponseFormat = WebMessageFormat.Json)]
        public string UsuarioCadastrarFoto()
        {
            string retorno = "[{'RESPOSTA':'OK'}]";
            try
            {
                string idUsuarioStr = HttpContext.Current.Request.Params["idUsuarioStr"];

                string foto = HttpContext.Current.Request.Params["foto"];

                int idUsuario = int.Parse(idUsuarioStr);

                if (foto != null && foto.Length > 10)
                {
                    if (idUsuario <= 0)
                    {
                        throw new Exception("ID do usuário não foi fornecido!");
                    }

                    if (Fachada.Instance.ProcurarUsuarioPorId(idUsuario) == null)
                    {
                        throw new Exception("ID do usuário não foi encontrado!");
                    }


                    var path = HttpContext.Current.Server.MapPath(@"\");

                    path = string.Format(@"{0}{1}{2}", path, @"Usuariofotos\", +idUsuario + ".jpg");

                    var diretorio = Path.GetDirectoryName(path);

                    if (!Directory.Exists(diretorio))
                    {
                        Directory.CreateDirectory(diretorio);
                    }

                    byte[] arrayFoto = Convert.FromBase64String(foto);

                    FileStream fileStream = new FileStream(path, FileMode.Create);

                    fileStream.Write(arrayFoto, 0, arrayFoto.Length);

                    fileStream.Close();
                }/**/
            }
            catch (Exception ex)
            {
                retorno = "[{'ERROR':'" + ex.Message + "'}]";
            }

            return retorno;
        }


        [WebGet(UriTemplate = "UsuarioCadastrar?nome={nome}&email={email}&senha={senha}&nascimento={nascimento}")]
        [OperationContract]
        public string UsuarioCadastrar(string nome, string email, string senha, string nascimento)
        {

            string retorno = "[{'ERROR':'Não foi possível salvar o usuário! Tente novamente.'}]";

            try
            {

                Usuario usuarioNovo = PessoaFactory.Instance.CreateUsuario();

                usuarioNovo.Nome = nome.Trim();
                usuarioNovo.Email = email.Trim();
                usuarioNovo.Nascimento = DateTime.Parse(nascimento.Trim());
                usuarioNovo.Senha = senha.Trim();

                Fachada.Instance.Salvar(usuarioNovo);

                if (usuarioNovo.Id > 0)//Confirmado inserção do usuário
                {
                    using (MemoryStream ms = new MemoryStream())
                    {
                        DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Usuario));
                        ser.WriteObject(ms, usuarioNovo);
                        retorno = "[" + System.Text.Encoding.UTF8.GetString(ms.ToArray()) + "]";
                    }
                }
            }
            catch (Exception e)
            {
                retorno = "[{'ERROR':'" + e.Message + "'}]";
            }

            return retorno;
        }

        [WebGet(UriTemplate = "UsuarioCadastrarLinha?idLinha={idLinha}&idUsuario={idUsuario}")]
        [OperationContract]
        public string UsuarioCadastrarLinha(int idLinha, int idUsuario)
        {
            string retorno = null;
            try
            {
                Linha l = Fachada.Instance.ProcurarLinhaPorId(idLinha);
                if (l != null)
                {
                    Usuario u = Fachada.Instance.ProcurarUsuarioPorId(idUsuario);
                    bool encontrouLinha = false;
                    foreach (UsuarioLinha item in u.UsuarioLinhas)
                    {
                        if (item.Linha.Id == idLinha)
                        {
                            encontrouLinha = true;
                            break;
                        }
                    }

                    if (!encontrouLinha)
                    {
                        UsuarioLinha uLinha = new UsuarioLinha();
                        uLinha.Linha = l;
                        u.AddUsuarioLinha(uLinha);
                        Fachada.Instance.Salvar(u);
                    }

                    retorno = "[{'RESPOSTA':'OK'}]";
                }
            }
            catch (Exception e)
            {
                retorno = "[{'ERROR':'" + e.Message + "'}]";
            }

            return retorno;
        }

        [OperationContract]
        [WebGet(UriTemplate = "GPSInserirLocalizacao?placa={placa}&latitude={latitude}&longitude={longitude}&velocidade={velocidade}")]
        public string GPSInserirLocalizacao(string placa, double latitude, double longitude, int velocidade)
        {
            string retorno = "[{'ERROR':'Não foi possível inserir localização!'}]";
            Localizacao l = null;

            try
            {

                Veiculo v = Fachada.Instance.ProcurarVeiculoPorPlaca(placa);

                if (v != null)
                {
                    l = new Localizacao();
                    if (velocidade > 0)
                    {
                        l.Velocidade = velocidade;
                    }
                    else
                    {
                        l.Velocidade = 0;
                    }

                    l.Latitude = latitude;
                    l.Longitude = longitude;
                    l.DataHoraServer = DateTime.Now;

                    v.AddLocalizacao(l);

                    Fachada.Instance.Salvar(l);

                    if (l.Id > 0)//Confirmado inserção da localização
                    {
                        retorno = "[{'RESPOSTA':'OK'}]";
                    }
                }
                else
                {
                    retorno = "[{'ERROR': 'Veículo/GPS não cadastrado!'}]";
                }
            }
            catch (Exception e)
            {
                retorno = "[{'ERROR':'" + e.Message + "'}]";
            }

            return retorno;
        }


        [OperationContract]
        [WebGet(UriTemplate = "ProcurarTransporteUsuarioMobile?IdUsuario={IdUsuario}&idLinha={idLinha}")]
        public string ProcurarTransporteUsuarioMobile(int IdUsuario, int idLinha)
        {
            string retorno = "[{'ERROR':'Usuário não encontrado!'}]";
            //IList<Localizacao> localizacoes = new List<Localizacao>();
            Localizacao l = null;

            try
            {
                Usuario usuarioLogado = Fachada.Instance.ProcurarUsuarioPorId(IdUsuario);

                if (usuarioLogado != null)
                {
                    retorno = null;
                    foreach (UsuarioLinha usuarioLinha in usuarioLogado.UsuarioLinhas)
                    {
                        if (idLinha == usuarioLinha.Linha.Id)
                        {
                            //Localizacao l = null;
                            l = Fachada.Instance.ProcurarUltimaLocalizacaoPorIdVeiculo(usuarioLinha.Linha.Veiculos[0].Id);

                            if (l != null)
                            {

                                //localizacoes.Add(l);
                            }

                            break;
                        }
                    }

                    using (MemoryStream ms = new MemoryStream())
                    {
                        DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Localizacao));
                        ser.WriteObject(ms, l);
                        retorno = "[" + System.Text.Encoding.UTF8.GetString(ms.ToArray()) + "]";
                    }/**/

                    //foreach (UsuarioLinha item in usuarioLogado.UsuarioLinhas)
                    //{

                    //break;
                    //}
                    /*Dictionary<string, object> lista = new Dictionary<string, object>();
                    lista.Add("Latitude", l.Latitude);
                    lista.Add("Longitude", l.Longitude);
                    lista.Add("Velocidade", l.Velocidade);
                    lista.Add("LinhaNome", l.Veiculo.Linha.Nome);
                    using (MemoryStream ms = new MemoryStream())
                    {
                        DataContractJsonSerializer ser = new DataContractJsonSerializer(lista.GetType());
                        ser.WriteObject(ms, lista);
                        retorno = System.Text.Encoding.UTF8.GetString(ms.ToArray());
                    }/**/


                    //retorno = "'Localizacao':[{'Latitude':" + l.Latitude + ",'Longitude':" + l.Longitude + ",'Velocidade':" + l.Velocidade + ",'LinhaNumero':'" + l.Veiculo.Linha.Numero + "','LinhaNome':'" + l.Veiculo.Linha.Nome + "'}]";
                    //retorno = "'Localizacao':[{'Latitude':" + l.Latitude + ",'Longitude':" + l.Longitude + ",'Velocidade':" + l.Velocidade + ",'LinhaNumero':'" + l.Veiculo.Linha.Numero + "','LinhaNome':'" + l.Veiculo.Linha.Nome + "'}]";

                }
            }
            catch (Exception e)
            {
                retorno = "[{'ERROR':'" + e.Message + "'}]";
            }

            return retorno;
        }


        [OperationContract]
        [WebInvoke(
            Method = "POST",
            BodyStyle = WebMessageBodyStyle.WrappedRequest,
            ResponseFormat = WebMessageFormat.Json)]
        public string ProcurarTransporteUsuarioWeb(int IdUsuario, int idLinha)
        {
            string retorno = "[{'ERROR':'Usuário não encontrado!'}]";
            //IList<Localizacao> localizacoes = new List<Localizacao>();
            Localizacao l = null;

            try
            {
                Usuario usuarioLogado = Fachada.Instance.ProcurarUsuarioPorId(IdUsuario);

                if (usuarioLogado != null)
                {
                    retorno = null;
                    foreach (UsuarioLinha usuarioLinha in usuarioLogado.UsuarioLinhas)
                    {
                        if (idLinha == usuarioLinha.Linha.Id)
                        {
                            //Localizacao l = null;
                            l = Fachada.Instance.ProcurarUltimaLocalizacaoPorIdVeiculo(usuarioLinha.Linha.Veiculos[0].Id);

                            if (l != null)
                            {

                                //localizacoes.Add(l);
                            }

                            break;
                        }
                    }

                    using (MemoryStream ms = new MemoryStream())
                    {
                        DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Localizacao));
                        ser.WriteObject(ms, l);
                        retorno = "[" + System.Text.Encoding.UTF8.GetString(ms.ToArray()) + "]";
                    }/**/

                    //foreach (UsuarioLinha item in usuarioLogado.UsuarioLinhas)
                    //{

                    //break;
                    //}
                    /*Dictionary<string, object> lista = new Dictionary<string, object>();
                    lista.Add("Latitude", l.Latitude);
                    lista.Add("Longitude", l.Longitude);
                    lista.Add("Velocidade", l.Velocidade);
                    lista.Add("LinhaNome", l.Veiculo.Linha.Nome);
                    using (MemoryStream ms = new MemoryStream())
                    {
                        DataContractJsonSerializer ser = new DataContractJsonSerializer(lista.GetType());
                        ser.WriteObject(ms, lista);
                        retorno = System.Text.Encoding.UTF8.GetString(ms.ToArray());
                    }/**/


                    //retorno = "'Localizacao':[{'Latitude':" + l.Latitude + ",'Longitude':" + l.Longitude + ",'Velocidade':" + l.Velocidade + ",'LinhaNumero':'" + l.Veiculo.Linha.Numero + "','LinhaNome':'" + l.Veiculo.Linha.Nome + "'}]";
                    //retorno = "'Localizacao':[{'Latitude':" + l.Latitude + ",'Longitude':" + l.Longitude + ",'Velocidade':" + l.Velocidade + ",'LinhaNumero':'" + l.Veiculo.Linha.Numero + "','LinhaNome':'" + l.Veiculo.Linha.Nome + "'}]";

                }
            }
            catch (Exception e)
            {
                retorno = "[{'ERROR':'" + e.Message + "'}]";
            }

            return retorno;
        }

        [OperationContract]
        [WebInvoke(
            Method = "POST",
            BodyStyle = WebMessageBodyStyle.WrappedRequest,
            ResponseFormat = WebMessageFormat.Json)]
        public string ProcurarParadasPorLinha(int idLinha)
        {
            string retorno = null;

            if (idLinha > 0)
            {
                Linha l = Fachada.Instance.ProcurarLinhaPorId(idLinha);

                Localizacao loc = Fachada.Instance.ProcurarUltimaLocalizacaoPorIdVeiculo(l.Veiculos[0].Id);

                if (l != null)
                {

                    IList<Parada> paradas = new List<Parada>();

                    foreach (LinhaParada linhaParada in l.LinhaParadas.ToList())
                    {
                        if (loc != null)
                        {
                            double distancia = Distance.GetDistanceBetweenPoints(linhaParada.Parada.Latitude, linhaParada.Parada.Longitude, loc.Latitude, loc.Longitude);
                            if (loc.Velocidade > 0)
                            {
                                double tempoChegada = distancia / (loc.Velocidade / 3.6);

                                TimeSpan tempo = TimeSpan.FromSeconds(tempoChegada);

                                linhaParada.Parada.TempoChegadaOnibus = Distance.HoraPorExtenso(tempo);

                            }
                            else
                            {
                                linhaParada.Parada.TempoChegadaOnibus = "Ônibus está parado!";
                            }

                        }
                        else
                        {
                            linhaParada.Parada.TempoChegadaOnibus = "Ônibus está indisponível";
                        }
                        paradas.Add(linhaParada.Parada);
                    }

                    using (MemoryStream ms = new MemoryStream())
                    {
                        DataContractJsonSerializer ser = new DataContractJsonSerializer(paradas.GetType());
                        ser.WriteObject(ms, paradas);
                        retorno = System.Text.Encoding.UTF8.GetString(ms.ToArray());
                    }
                }
                else
                {
                    retorno = "[{'ERROR':'Linha não encontrada!'}]";
                }
            }

            return retorno;
        }

        [OperationContract]
        [WebGet(UriTemplate = "ProcurarParadasPorLinhaUsuario?idLinha={idLinha}")]
        public string ProcurarParadasPorLinhaUsuario(int idLinha)
        {
            string retorno = null;

            if (idLinha > 0)
            {

                /*try
                {
                    Uri uri = new Uri("http://maps.google.com/maps/nav?hl=pt-BR&gl=pt-BR&output=js&oe=utf8&q=from%3A_FROM_+to%3A_TO_'");

                    WebRequest http = HttpWebRequest.Create(uri);
                    HttpWebResponse response = (HttpWebResponse)http.GetResponse();
                    Stream stream = response.GetResponseStream();
                }   
                catch (UriFormatException e)
                {
                    Console.WriteLine("Invalid URL");
                }
                catch (IOException e)
                {
                    Console.WriteLine("Could not connect to URL");
                }/**/

                Linha l = Fachada.Instance.ProcurarLinhaPorId(idLinha);


                Localizacao loc = null;

                foreach (Veiculo v in l.Veiculos.ToList())
                {
                    loc = Fachada.Instance.ProcurarUltimaLocalizacaoPorIdVeiculo(v.Id);
                    break;
                }

                

                if (loc != null)
                {

                    IList<Parada> paradas = new List<Parada>();

                    foreach (LinhaParada linhaParada in l.LinhaParadas.ToList())
                    {
                        if (loc != null)
                        {
                            double distancia = Distance.GetDistanceBetweenPoints(linhaParada.Parada.Latitude, linhaParada.Parada.Longitude, loc.Latitude, loc.Longitude);
                            if (loc.Velocidade > 0)
                            {
                                double tempoChegada = distancia / (loc.Velocidade / 3.6);

                                TimeSpan tempo = TimeSpan.FromSeconds(tempoChegada);

                                linhaParada.Parada.TempoChegadaOnibus = Distance.HoraPorExtenso(tempo);

                            }
                            else
                            {
                                linhaParada.Parada.TempoChegadaOnibus = "Ônibus está parado!";
                            }

                        }
                        else
                        {
                            linhaParada.Parada.TempoChegadaOnibus = "Ônibus está indisponível";
                        }
                        paradas.Add(linhaParada.Parada);
                    }

                    using (MemoryStream ms = new MemoryStream())
                    {
                        DataContractJsonSerializer ser = new DataContractJsonSerializer(paradas.GetType());
                        ser.WriteObject(ms, paradas);
                        retorno = System.Text.Encoding.UTF8.GetString(ms.ToArray());
                    }
                }
                else
                {
                    retorno = "[{'ERROR':'Linha/Veiculo não encontrado!'}]";
                }
            }

            return retorno;
        }


        [OperationContract]
        [WebGet]
        public string ProcurarLinhaTodos()
        {
            string retorno = null;

            IList<Linha> linhas = Fachada.Instance.ProcurarLinhaTodos();

            using (MemoryStream ms = new MemoryStream())
            {
                DataContractJsonSerializer ser = new DataContractJsonSerializer(linhas.GetType());
                ser.WriteObject(ms, linhas);
                retorno = System.Text.Encoding.UTF8.GetString(ms.ToArray());
            }

            return retorno;
        }

        [OperationContract]
        [WebGet(UriTemplate = "ProcurarHorarioPorLinhaTodos?idLinha={idLinha}")]
        public string ProcurarHorarioPorLinhaTodos(int idLinha)
        {
            string retorno = null;

            Linha linha = Fachada.Instance.ProcurarLinhaPorId(idLinha);



            using (MemoryStream ms = new MemoryStream())
            {
                DataContractJsonSerializer ser = new DataContractJsonSerializer(linha.Horarios.GetType());
                ser.WriteObject(ms, linha.Horarios);
                retorno = System.Text.Encoding.UTF8.GetString(ms.ToArray());
            }

            return retorno;
        }


        [OperationContract]
        [WebGet(UriTemplate = "RemoverLinhaUsuario?IdUsuario={IdUsuario}&idLinha={idLinha}")]
        public string RemoverLinhaUsuario(int idUsuario, int idLinha)
        {
            string retorno = null;
            try
            {
                Usuario u = Fachada.Instance.ProcurarUsuarioPorId(idUsuario);

                foreach (UsuarioLinha item in u.UsuarioLinhas)
                {
                    if (item.Linha.Id == idLinha)
                    {
                        u.UsuarioLinhas.Remove(item);
                        Fachada.Instance.Salvar(u);
                        break;
                    }
                }

                retorno = "[{'RESPOSTA':'OK'}]";
            }
            catch (Exception e)
            {
                retorno = "[{'ERROR':'" + e.Message + "'}]";
            }

            return retorno;
        }


        [OperationContract]
        [WebGet(UriTemplate = "SalvarLocationUsuario?IdUsuario={IdUsuario}&latitude={latitude}&longitude={longitude}")]
        public void SalvarLocationUsuario(int idUsuario, double latitude, double longitude)
        {
            Usuario u = Fachada.Instance.ProcurarUsuarioPorId(idUsuario);
            if ((u != null) && (latitude != 0) && (longitude != 0))
            {
                u.Latitude = latitude;
                u.Longitude = longitude;

                Fachada.Instance.Salvar(u);
            }
        }



        /*private byte[] Base64ToImage(string base64String)
        {
            // Convert Base64 String to byte[]
            return Convert.FromBase64String(base64String);
            /*MemoryStream ms = new MemoryStream(imageBytes, 0,
              imageBytes.Length);

            // Convert byte[] to Image
            ms.Write(imageBytes, 0, imageBytes.Length);
            Image image = Image.FromStream(ms, true);
            return ms;
        }

        private string ImageToBase64(Image image,
  System.Drawing.Imaging.ImageFormat format)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                // Convert Image to byte[]
                image.Save(ms, format);
                byte[] imageBytes = ms.ToArray();

                // Convert byte[] to Base64 String
                string base64String = Convert.ToBase64String(imageBytes);
                return base64String;
            }
        }/**/
    }


}
